﻿package de.gameduell.framework.fakeserver {
	import de.gameduell.framework.application.protocol.Protocol;
	import de.gameduell.framework.debug.Debug;
	import de.gameduell.framework.fakeserver.FakeServerEvent;
	import de.gameduell.framework.fakeserver.Storyboard;
	import de.gameduell.net.src.communication.BaseCommunication;
	import de.gameduell.net.src.communication.CommunicationEvent;
	import de.gameduell.net.src.communication.ICommunication;
	import de.gameduell.net.src.communication.ServerMessageEvent;
	import de.gameduell.net.src.message.IMessage;
	
	import flash.events.Event;	

	public class AutomatedCommunication extends BaseCommunication implements ICommunication {

		protected var fakeServer:IFakeServer;
		private var storyboard:Storyboard;
		private var storyboardIndex:int = 0;
		protected var awaitedMessages:Array = new Array();
		protected var variables:Array = new Array();
		private var lastMessage:IMessage;

		public function AutomatedCommunication(storyboardXml:XML,aFakeServer:IFakeServer = null) {
			storyboard = new Storyboard(storyboardXml);
			if(aFakeServer != null){
				fakeServer = aFakeServer;
				fakeServer.addEventListener(FakeServerEvent.SERVER_MESSAGE, onFakeServerMessage);
				fakeServer.addEventListener(Storyboard.AUTOMATE_OFF, startStoryboard);
			}
			super("Standalone");
		}
		
		private function onFakeServerMessage(event:FakeServerEvent):void {
			Debug.trace("onFakeServerMessage");
			dispatchEvent(event.message);
		}

		public function connect():void {
			dispatchEvent(new CommunicationEvent(CommunicationEvent.CONNECTED));
		}

		public function send(requestType:String, parameters:Array):IMessage {
			Debug.trace("AutomatedCommunication::send requestType \n" + requestType + " \t " + parameters, Debug.SEND);
			if (fakeServer != null) {
				fakeServer.readMessage(requestType, parameters);
			}
			lastMessage = protocol.createMessage(requestType, parameters, messageQueue.nextMessageId);
			switch(requestType) {
				case Protocol.LOADED:
					dispatchEvent(new ServerMessageEvent(Protocol.LOADED, []));
					startStoryboard();
					break;
				default:
					if (isAwaitedMessage(requestType, parameters) && (fakeServer == null || !fakeServer.isOn)) {
						startStoryboard();
					}
					break;
			}
			return lastMessage;
		}

		protected function startStoryboard(event:Event = null):void {
//			Debug.trace("AutomatedCommunication::startStoryboard: storyboardIndex "+storyboardIndex);
			playStoryboard(readStoryboard(storyboard.messages));
		}

		private function readStoryboard(storyboardMessages:Array):Array {
			var serverMessages:Array = new Array();
			for (var i:int = storyboardIndex;i < storyboardMessages.length;i++) {
				var storyboardMessage:Array = storyboardMessages[i];
				var messageType:String = storyboardMessage[0];
//				Debug.trace("AutomatedCommunication::readStoryboard:messageType " + messageType);
				
				if (messageType == Storyboard.WAIT) {
					storyboardIndex = i + 1;
					awaitedMessages = storyboardMessage[1];
					onWaitNode(storyboardMessage, serverMessages);
					break;
				}
				else if (messageType == Storyboard.AUTOMATE) {
					storyboardIndex++;
					serverMessages.push([messageType,[]]);
				}
				else if (messageType == Storyboard.CHOICE) {
					var choiceContent:Array = storyboardMessage[1];
					for (var j in choiceContent) {
						if (lastMessage != null && lastMessage.requestType == choiceContent[j][0] && lastMessage.parameters == choiceContent[j][2]) {
							var optionalMessages:Array = choiceContent[j][1];
							for (var l in optionalMessages) {
								storyboardMessages.splice(i + 1 + l, 0, optionalMessages[l]);
							}
						}
					}
				} else {
					if(storyboardMessage.length == 3) {
						var storyboardsVars:Array = storyboardMessage[2];
						for (var k in storyboardsVars) {
							var variablePos:int = storyboardsVars[k][0];
							var variableName:String = storyboardsVars[k][1];
							storyboardMessage[1][variablePos] = variables[variableName];
						}
					}
					serverMessages.push([messageType,storyboardMessage[1]]);
				}
			}
			return serverMessages;
		}

		protected function onWaitNode(storyboardMessage:Array,serverMessages:Array):void {
		}

		private function playStoryboard(serverMessages:Array):void {
			for (var j:int = 0;j < serverMessages.length; j++) {
				reply(serverMessages[j][0], serverMessages[j][1]);
			}
		}
//
//		protected function onAutamate(event:ServerMessageEvent):void {
//			Debug.trace("AutomatedCommunication::forwardReply " + " \n" + event.type + "\t" + event.parameters, Debug.RECEIVE);
//			dispatchEvent(new ServerMessageEvent(event.type, event.parameters));
//		
//			if (isAwaitedMessage(event.type, event.parameters)) {
////				Debug.trace("AutomatedCommunication::forwardReply isAwaitedMessage, playStoryboard", Debug.DEBUG);
//				if (fakeServer != null) {
//					fakeServer.switchOff();
//				}
//				startStoryboard();
//			}
//		}

		private function reply(messageType:String,messageBody:Array):void {
			Debug.trace("AutomatedCommunication::reply \n" + messageType + "\t" + messageBody, Debug.RECEIVE);
			if (fakeServer != null) {
				fakeServer.readMessage(messageType, messageBody);
			}
			if(messageType != Storyboard.AUTOMATE) {
				dispatchEvent(new ServerMessageEvent(messageType, messageBody));
			} else if(fakeServer != null){
				fakeServer.switchOn();
			} else {
				Debug.trace("AutomatedCommunication::reply message type is " + messageType + " but fakeServer is " + fakeServer, Debug.ERROR);
			}
		}

		protected function isAwaitedMessage(requestType:String, parameters:Array):Boolean {
//			Debug.trace("AutomatedCommunication::isAwaitedMessage " + requestType + "\t" + parameters, Debug.DEBUG);
			var isAwaited:Boolean = false;
			for (var i in awaitedMessages) {
				if(awaitedMessages[i][0] == requestType) {
					if (awaitedMessages[i][1].toString() == "" || (parameters.toString() == awaitedMessages[i][1].toString())) {
						isAwaited = true;
						break;
					} else {
//						Debug.trace("AutomatedCommunication::isAwaitedMessage " + parameters + "!=" + awaitedMessages[i][1].toString(), Debug.DEBUG);
					}
				} else {
//					Debug.trace("AutomatedCommunication::isAwaitedMessage " + requestType + "!=" + awaitedMessages[i][0].toString(), Debug.DEBUG);
				}
			}
			return isAwaited;
		}

		public function sync():void {
		}

		public function terminate():void {
		}

		public function get debugModeEnabled():Boolean {
			return true;
		}
	}
}